<template>
  <!-- 头部控制台 -->
  <div class="file-header">
    <div class="top">
      <div class="ace-btns">
        <div class="btn-child" @click="pathBack">
          <span class="iconfont icon-arrowLeft-fill" />
        </div>
        <div class="btn-child" @click="refresh">
          <span class="iconfont icon-shuaxin" />
        </div>
        <div
          class="btn-child"
          @click="$store.commit('stateUpdate', { name: 'path', data: '' })"
        >
          <span class="iconfont icon-home" />
        </div>
      </div>
      <div class="ace-path">
        <span>oss://{{ bucket }}/{{ path }}</span>
      </div>
      <div class="ace-btns">
        <div
          class="btn-child"
          style="border-right: 1px solid rgba(0, 0, 0, 0.2)"
          @click="collection"
        >
          <span :class="star" />
        </div>
      </div>
    </div>
    <div class="bottom">
      <div class="ace-btns">
        <div class="btn-child">
          <i class="iconfont icon-shangchuan" />
          <span>文件</span>
          <input type="file" multiple @change="dirUpload">
        </div>
        <div class="btn-child">
          <i class="iconfont icon-shangchuan" />
          <span>目录</span>
          <input
            type="file"
            webkitdirectory
            directory
            multiple
            @change="dirUpload"
          >
        </div>
        <div class="btn-child" @click="mkdirFileClick">
          <i class="iconfont icon-jia" />
          <span>创建目录</span>
        </div>
        <div class="btn-child" @click="downloadAddressClick">
          <i class="iconfont icon-xiazai3" />
          <span>批量选定</span>
        </div>
        <div class="btn-child" @click="clipClick">
          <i class="iconfont icon-ziyuan" style="color: #2ab4ff" />
          <span>图片裁剪</span>
        </div>
        <div class="btn-child" @click="copyClick(null)">
          <i class="iconfont icon-fuzhi" />
          <span>复制</span>
        </div>
        <div class="btn-child" @click="copyClick(true)">
          <i class="iconfont icon-jianqie" />
          <span>移动</span>
        </div>
        <div
          class="btn-child"
          style="border-right: 1px solid rgba(0, 0, 0, 0.2)"
          @click="operationClick('delete')"
        >
          <i class="iconfont icon-dashujukeshihuaico-" />
          <span>删除</span>
        </div>
        <div v-if="copys.length > 0" class="paste">
          <div class="paste-child" @click="pasteClick">
            <i class="iconfont icon-niantie" />
            <span>粘贴 ({{ copys.length }})</span>
          </div>
          <span
            class="iconfont icon-dashujukeshihuaico-"
            @click="cancelPasteClick"
          />
        </div>
      </div>
    </div>

    <el-dialog
      title="创建目录"
      :visible.sync="mkdirVisible"
      width="400px"
      :before-close="handleClose"
      append-to-body
    >
      <div class="mkdir">
        <span>目录名称</span>
        <el-input v-model="mkdirName" placeholder="目录名称" />
      </div>
      <div class="mkdir-btn">
        <div class="ace-btns">
          <div class="btn-child" @click="mkdirClick">
            <i class="iconfont icon-queding1" />
            <span>确定</span>
          </div>
          <div class="btn-child" @click="mkdirVisible = false">
            <i class="iconfont icon-dashujukeshihuaico-" />
            <span>取消</span>
          </div>
        </div>
      </div>
    </el-dialog>

    <el-dialog
      :title="deleteConfirm ? '文件删除' : '将删除以下目录和文件'"
      :visible.sync="deleteVisible"
      width="600px"
      :before-close="() => closeFun('deleteVisible', false)"
      append-to-body
    >
      <div v-if="deleteConfirm" class="delete-progress">
        <span>{{
          this.deleteTotal > 1000
            ? "删除文件数量超限，可能会受到OSS服务器的并发限制，正在删除......"
            : "正在删除......"
        }}</span>
        <div class="delete-child">
          <span
            :style="{ width: Percentage(deleteNum, deleteTotal) + '%' }"
          />
        </div>
        <span>{{ deleteNum }} / {{ deleteTotal }}</span>
      </div>
      <div v-if="!deleteConfirm" class="delete-list">
        <div
          v-for="(item, index) in selections"
          :key="index"
          class="delete-child"
        >
          <svg class="icon" aria-hidden="true">
            <use
              :xlink:href="
                item.name[item.name.length - 1] === '/'
                  ? '#icon-wenjianjia'
                  : suffixIconTool(item)
              "
            />
          </svg>

          <span>{{ item.name }}</span>
        </div>
      </div>
      <div class="mkdir-btn">
        <div class="ace-btns">
          <div v-if="!deleteConfirm" class="btn-child" @click="deleteFile">
            <i class="iconfont icon-queding1" />
            <span>确定</span>
          </div>
          <div class="btn-child" @click="closeFun('deleteVisible', false)">
            <i class="iconfont icon-dashujukeshihuaico-" />
            <span>关闭</span>
          </div>
        </div>
      </div>
    </el-dialog>

    <el-dialog
      title="拷贝"
      :visible.sync="copyVisible"
      width="600px"
      :before-close="() => closeFun('copyVisible', false)"
      append-to-body
    >
      <div class="copy-progress">
        <span>{{
          this.copyTotal > 1000
            ? "由于拷贝文件数量超限，可能会受到OSS服务器的并发限制，正在粘贴......"
            : "正在粘贴......"
        }}</span>
        <div class="copy-child">
          <span :style="{ width: Percentage(copyNum, copyTotal) + '%' }" />
        </div>
        <span>{{ copyNum }} / {{ copyTotal }}</span>
      </div>

      <div class="mkdir-btn">
        <div class="ace-btns">
          <div class="btn-child" @click="closeFun('copyVisible', false)">
            <i class="iconfont icon-dashujukeshihuaico-" />
            <span>关闭</span>
          </div>
        </div>
      </div>
    </el-dialog>

    <el-dialog
      :title="`下载地址[${downloads.length}]`"
      width="1000px"
      :visible.sync="downloadVisible"
      :before-close="() => closeFun('downloadVisible', false)"
      append-to-body
    >
      <div class="delete-list">
        <div
          v-for="(item, index) in downloads"
          :key="index"
          class="delete-child"
        >
          <svg class="icon" aria-hidden="true">
            <use
              :xlink:href="
                item.name[item.name.length - 1] === '/'
                  ? '#icon-wenjianjia'
                  : suffixIconTool(item)
              "
            />
          </svg>
          <span>{{ item.url }}</span>
        </div>
      </div>
      <div class="mkdir-btn">
        <div class="ace-btns">
          <div class="btn-child" @click="closeFun('downloadVisible', false)">
            <i class="iconfont icon-dashujukeshihuaico-" />
            <span>关闭</span>
          </div>
        </div>
      </div>
    </el-dialog>

    <el-dialog
      title="图片裁剪-控制台"
      width="1400px"
      top="20px"
      class="clip-dialog"
      :close-on-click-modal="false"
      :visible.sync="clipVisible"
      :before-close="(none) => none()"
      append-to-body
    >
      <div class="clip">
        <clip
          v-if="clipVisible"
          :img-files="ImgFiles"
          :is-file="false"
          @close="() => (clipVisible = false)"
        />
      </div>
      <div class="mkdir-btn">
        <div class="ace-btns">
          <div class="btn-child" @click="clipVisible = false">
            <i class="iconfont icon-dashujukeshihuaico-" />
            <span>关闭</span>
          </div>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { mapState } from 'vuex'
import {
  fileList,
  multipartUpload,
  simplePut,
  deleteMulti,
  deleteKey,
  allList,
  maxList,
  signatureUrl,
  copy,
  getClient
} from '@/api'
import { uuid, Percentage } from '@/tool'
import clip from '@/components/AliOss/clip'
import OSS from 'ali-oss'
export default {
  name: '',
  components: { clip },
  props: {},
  data() {
    return {
      star: '',
      Percentage,
      mkdirVisible: false,
      clipVisible: false,
      ImgFiles: [],
      mkdirName: '',
      suffixs: []
    }
  },
  computed: mapState({
    // 箭头函数可使代码更简练
    path: (state) => state.path,
    uploadList: (state) => state.uploadList,
    selections: (state) => state.selections,
    copys: (state) => state.copys,
    copyPath: (state) => state.copyPath,
    copyNum: (state) => state.copyNum,
    copyTotal: (state) => state.copyTotal,
    copyVisible: (state) => state.copyVisible,
    deleteNum: (state) => state.deleteNum,
    deleteTotal: (state) => state.deleteTotal,
    deleteVisible: (state) => state.deleteVisible,
    deleteConfirm: (state) => state.deleteConfirm,
    shear: (state) => state.shear,
    downloadVisible: (state) => state.downloadVisible,
    downloads: (state) => state.downloads,
    bucket: (state) => state.bucket,
    bookmarksRefreshDelete: (state) => state.bookmarksRefreshDelete
  }),
  watch: {
    path() {
      this.refresh()
    },
    bookmarksRefreshDelete() {
      this.refresh()
    }
  },
  created() {},
  async mounted() {
    this.collectionStatus()
  },
  methods: {
    async clipClick() {
      const _this = this
      const ImgFiles = []
      await this.selections.map(async(item) => {
        if (_this.imgSuffixTool(item.name)) {
          ImgFiles.push({
            name: _this.dirTitleTool(item),
            path: item.name,
            url: await signatureUrl(item.name)
          })
        }
      })
      if (ImgFiles.length < 1) {
        return
      }
      this.ImgFiles = ImgFiles

      this.clipVisible = true
    },

    mkdirFileClick() {
      this.mkdirName = ''
      this.mkdirVisible = true
    },
    closeFun(name, data) {
      this.$store.commit('stateUpdate', { name, data })
    },
    async downloadAddressClick() {
      if (this.selections.length < 1) {
        return
      }
      this.closeFun('downloads', [])
      // this.closeFun('downloadVisible', true)
      const list = await this.$store.dispatch('getfiles', this.selections)
      this.closeFun('downloads', list)
      this.$message({
        type: 'success',
        message: '选定成功，已加载到标记队列~'
      })
    },
    operationClick(type) {
      if (this.selections.length < 1) {
        this.$message.error('错误，勾选数据为空')
        return
      }
      if (type === 'delete') {
        this.$store.commit('stateUpdate', {
          name: 'deleteVisible',
          data: true
        })
      }
    },
    /*
      由于SDK限制每次所请求的目录内文件最多返回1000个文件
      该方法递归循环子目录文件列表
    */
    async infiniteList(nextMarker) {
      let max = nextMarker
      let flag = true
      const files = []
      while (flag) {
        const res = await maxList(max)
        max = res.nextMarker
        flag = res.isTruncated
        files.push(...res.objects)
      }
      return files
    },

    // 粘贴文件
    async pasteClick() {
      // emptys 参数为剪切模式的所需删除文件列表
      this.$store.dispatch('pasteClick', { emptys: this.copys })
    },
    // 取消粘贴
    cancelPasteClick() {
      this.$store.commit('stateUpdate', { name: 'copys', data: [] })
    },
    // 裁剪/复制
    async copyClick(type) {
      this.$store.commit('stateUpdate', { name: 'shear', data: type })
      this.$store.commit('stateUpdate', {
        name: 'copys',
        data: this.selections
      })
      this.$store.commit('stateUpdate', { name: 'copyPath', data: this.path })
    },
    // 批量删除
    async deleteFile() {
      this.$store.dispatch('deleteFile', this.selections)
    },
    // 创建目录
    async mkdirClick() {
      // 检测字符串是否全为空格
      const empty = this.mkdirName.match(/^\s+$/)
      // 空字符串和全空格，抛出异常
      if (empty != null || !this.mkdirName) {
        this.$message.error('目录名称非法')
        return
      }
      // 关闭对话框
      this.mkdirVisible = false
      // 创建目录
      await simplePut(`${this.path}${this.mkdirName}/`, new Blob(['']))
      // 更新【文件/目录】列表
      this.$store.dispatch('fileUpdate')
    },
    handleClose(none) {
      none()
    },
    dirUpload(e) {
      const files = Array.from(e.target.files)
      e.target.value = ''
      files.map((file) => {
        this.$store.dispatch('sliceUpload', { file })
      })
    },
    // 刷新
    async refresh() {
      await this.$store.dispatch('fileUpdate')
      this.collectionStatus()
    },
    // 后退
    pathBack() {
      const path = this.path
      const paths = path.split('/')
      paths.splice(paths.length - 2, 1)
      this.$store.commit('stateUpdate', {
        name: 'path',
        data: paths.join('/')
      })
      this.refresh()
    },
    // 书签状态更新
    collectionStatus() {
      let star = 'iconfont icon-xingxing'
      const { accessKeyId } =
        JSON.parse(window.localStorage.getItem('ossInfo')) || {}
      const bookmarks =
        JSON.parse(window.localStorage.getItem([accessKeyId])) || {}
      const items = bookmarks[`${this.bucket}_book`] || []
      items.map((item) => {
        if (this.path === item.path) {
          star = 'iconfont icon-pingjiaxingxing'
        }
      })
      this.star = star
    },
    // 添加书签
    collection() {
      const { accessKeyId } =
        JSON.parse(window.localStorage.getItem('ossInfo')) || {}
      const bookmarks =
        JSON.parse(window.localStorage.getItem([accessKeyId])) || {}
      let items = bookmarks[`${this.bucket}_book`] || []
      const list = []
      let flag = true
      let message = '书签添加成功'
      items.map((item) => {
        if (this.path === item.path) {
          flag = false
        } else {
          list.push({ path: item, date: Math.round(new Date()) })
        }
      })
      if (flag) {
        items.push({ path: this.path, date: Math.round(new Date()) })
      } else {
        items = list
        message = '书签删除成功'
      }

      bookmarks[`${this.bucket}_book`] = items

      window.localStorage.setItem([accessKeyId], JSON.stringify(bookmarks))

      this.collectionStatus()
      this.$notify({
        title: '书签更新',
        message: `<p style="word-break:break-all;width:260px">${accessKeyId}<br/><span style="color:#e02433">${message}</span></p>`,
        type: 'success',
        position: 'top-left',
        duration: 3000,
        dangerouslyUseHTMLString: true
      })
    },
    // 文件名加工
    dirTitleTool({ name, dir }) {
      const names = name.split('/')

      const fileName = dir ? names[names.length - 2] : names[names.length - 1]

      return dir ? fileName + '/' : fileName
    },
    imgSuffixTool(name) {
      const names = name.split('.')
      let flag = false
      name = names[names.length - 1]
      if (
        name === 'png' ||
        name === 'jpeg' ||
        name === 'jpg' ||
        name === 'gif' ||
        name === 'webp'
      ) {
        flag = true
      }
      return flag
    },
    // 后缀Icon加工
    suffixIconTool(row) {
      if (row.dir) {
        return '#icon-wenjianjia'
      }
      let icon = '#icon-wendang1'
      const names = row.name.split('.')
      const suffix = names[names.length - 1]
      suffix === 'zip' && (icon = '#icon-yasuobao')
      suffix === 'pdf' && (icon = '#icon-pdf')
      suffix === 'docx' && (icon = '#icon-WORD')
      suffix === 'doc' && (icon = '#icon-WORD')
      suffix === 'md' && (icon = '#icon-file-markdown')
      suffix === 'vue' && (icon = '#icon-Vue')
      suffix === 'java' && (icon = '#icon-java')
      suffix === 'js' && (icon = '#icon-js')
      suffix === 'jsx' && (icon = '#icon-jsx')
      suffix === 'php' && (icon = '#icon-php')
      suffix === 'css' && (icon = '#icon-CSS1')
      suffix === 'less' && (icon = '#icon-CSS1')
      suffix === 'scss' && (icon = '#icon-CSS1')
      suffix === 'xlsx' && (icon = '#icon-xlsx')
      suffix === 'json' && (icon = '#icon-JSON')
      suffix === 'txt' && (icon = '#icon-TXT')
      suffix === 'png' && (icon = '#icon-huabanfuben')
      suffix === 'jpg' && (icon = '#icon-huabanfuben')
      suffix === 'jpeg' && (icon = '#icon-huabanfuben')
      suffix === 'gif' && (icon = '#icon-huabanfuben')
      suffix === 'webp' && (icon = '#icon-huabanfuben')
      suffix === 'svg' && (icon = '#icon-huabanfuben')
      suffix === 'icon' && (icon = '#icon-huabanfuben')
      suffix === 'psd' && (icon = '#icon-PSDtubiao')
      suffix === 'exe' && (icon = '#icon-windows')
      suffix === 'html' && (icon = '#icon-chrome')
      suffix === 'htm' && (icon = '#icon-chrome')
      suffix === 'xml' && (icon = '#icon-xml')
      suffix === 'ts' && (icon = '#icon-ts')
      return icon
    }
  }
}
</script>

<style lang="scss">
.clip-dialog .el-dialog {
  margin: 0 auto;
}
</style>

<style scoped lang="scss">
.ace-btns {
  height: 30px;
  display: flex;
  align-items: center;
  box-sizing: border-box;
  margin-right: 0px;
  user-select: none;
  .btn-child {
    height: 30px;
    min-width: 40px;
    padding: 0 8px;
    background-color: #fff;
    box-sizing: border-box;
    border: 1px solid rgba($color: #888, $alpha: 0.3);
    border-right: 0px;
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    input[type="file"] {
      opacity: 0;
      position: absolute;
      left: 0;
      top: -100%;
      width: 100%;
      height: 200%;
      cursor: pointer;
    }
    > span {
      font-size: 14px;
      margin-left: 3px;
    }
    > .icon-jia {
      color: #3c763d;
      font-weight: 700;
    }
    > .icon-shangchuan {
      color: #31708f;
    }
    &:hover {
      background-color: #e6e6e6;
    }
    &:active {
      background-color: #f5f5f5;
    }
  }
}

.paste {
  height: 30px;
  border: 1px solid rgba($color: #000000, $alpha: 0.1);
  border-left: 0px;
  display: flex;
  align-items: center;
  padding-right: 16px;
  position: relative;
  box-sizing: border-box;
  cursor: pointer;
  > .paste-child {
    width: 100%;
    height: 100%;
    padding-right: 4px;
    display: flex;
    align-items: center;
    &:hover {
      background-color: #f5f5f5;
    }
    > i {
      color: #409eff;
    }
    > span {
      height: 100%;
      display: flex;
      align-items: center;
      margin-left: 2px;
    }
  }

  > span {
    width: 16px;
    height: 100%;
    display: flex;
    align-items: center;
    border-left: 1px solid rgba($color: #888, $alpha: 0.2);
    position: absolute;
    right: 0;
    top: 0;
    cursor: pointer;
    &:hover {
      background-color: #f5f5f5;
    }
  }
}

.copy-progress,
.delete-progress {
  width: 100%;
  height: 100px;
  padding: 0 8px;
  box-sizing: border-box;
  > span:nth-child(1) {
    display: block;
    margin-top: 14px;
    font-size: 16px;
    color: #888;
  }
  > span:nth-child(3) {
    font-size: 13px;
    color: #000;
    font-weight: 700;
    margin-top: 6px;
  }
  > span {
    display: block;
    margin-top: 14px;
    font-size: 16px;
    color: #888;
  }
  .copy-child,
  .delete-child {
    width: 100%;
    height: 22px;
    background-color: #f5f5f5;
    border-radius: 4px;
    overflow: hidden;
    margin-top: 10px;
    > span:nth-child(1) {
      height: 100%;
      display: block;
      background-color: #5cb85c;
    }
  }
}
</style>

<style scoped lang="scss">
.mkdir {
  width: 100%;
  height: 100px;
  display: flex;
  align-items: center;
  padding: 10px 20px;
  box-sizing: border-box;
  border-top: 1px solid rgba($color: #888, $alpha: 0.2);
  > span {
    width: 120px;
    font-size: 18px;
    font-weight: 700;
  }
}
.mkdir-btn {
  width: 100%;
  height: 40px;
  border-top: 1px solid rgba($color: #888, $alpha: 0.2);
  background-color: #f6f6f6;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 0 6px;
  box-sizing: border-box;
  .ace-btns {
    .btn-child {
      border: 1px solid rgba($color: #888, $alpha: 0.2);
      border-radius: 5px;
      margin-left: 10px;
      > i {
        margin-top: 1px;
      }
    }

    .btn-child:nth-child(1) {
      background-color: #5cb85c;
      color: #fff;
      &:hover {
        background-color: #449d44;
      }
      &:active {
        background-color: #398439;
      }
      > i {
        color: #fff;
        margin-top: 1px;
      }
    }
  }
}
.delete-list {
  width: 100%;
  padding: 4px 10px;
  box-sizing: border-box;
  margin-top: 0px;
  height: 400px;
  overflow: auto;
  .delete-child {
    width: 100%;
    font-size: 15px;
    display: flex;
    align-items: center;
    > span {
      margin-left: 5px;
      color: #333;
      font-size: 14px;
    }
  }
}
</style>

<style scoped lang="scss">
.file-header {
  width: 100%;
  height: 75px;
  box-sizing: border-box;
  > .top {
    width: 100%;
    height: 40px;
    display: flex;
    align-items: center;
    box-sizing: border-box;
    padding: 0 10px;
    .ace-path {
      width: 100%;
      background-color: #fff;
      box-sizing: border-box;
      height: 30px;
      border: 1px solid rgba($color: #888, $alpha: 0.3);
      border-right: 0px;
      display: flex;
      align-items: center;
      padding-left: 10px;
      > span {
        color: #555;
        font-weight: 900;
        font-size: 13px;
      }
    }
  }
  > .bottom {
    width: 100%;
    height: 35px;
    background-color: #fff;
    box-sizing: border-box;
    padding: 0 10px;
    border-bottom: 1px solid rgba($color: #000000, $alpha: 0.1);
    display: flex;
  }
}
</style>

